package com.intramirror.product.schedule;

import com.intramirror.product.entity.AggregateRule;
import com.intramirror.product.entity.Product;
import com.intramirror.product.exception.BusinessException;
import com.intramirror.product.service.IAggregateService;
import com.intramirror.product.utils.AggregateRuleManagement;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * Created on 2018/1/30.
 * @author 123
 */
@PropertySource(value = "classpath:${spring.profiles.active}/schedule.properties")
@Component
public class AggregateSchedule {
    private static final Logger LOGGER = LoggerFactory.getLogger(AggregateSchedule.class);
    private static final long ONE_MINUTE = 60 * 1000;
    private static final int PROCESS_PRODUCT_NUM = 1000;
    private static int count = 0;

    @Value("${delay.minutes}")
    private Integer delayMinutes;

    public Integer getDelayMinutes() {
        return delayMinutes;
    }

    public void setDelayMinutes(Integer delayMinutes) {
        this.delayMinutes = delayMinutes;
    }

    @Autowired
    IAggregateService aggregateService;

    @Scheduled(fixedDelay = ONE_MINUTE)
    public void fixedDelayJob() throws InterruptedException {

        if (count++ % delayMinutes != 0) {
            return;
        }

        if (!AggregateRuleManagement.getInstance().getAggregateFlag()) {
            LOGGER.info("Aggregate schedule is stopped.");
            return;
        }

        List<AggregateRule> listRule = aggregateService.listAllAggregateRule();
        AggregateRuleManagement.getInstance().setRuleList(listRule);

        LOGGER.info("*********************************************************");
        LOGGER.info("**************Start to run aggregate product*************");
        LOGGER.info("*********************************************************");

        Map<Long, List<Long>> vendorIdForBrandIdMap = new HashMap<>();
        //如果存在brandId为-1，则需要查询该vendor下所有的商品，否则只需要查询该vendor下设置了规则的brand对应的商品
        for (AggregateRule aggregateRule : listRule) {
            Long vendorId = aggregateRule.getVendorId();
            List<Long> brandIds;
            if (vendorIdForBrandIdMap.containsKey(vendorId)) {
                if (aggregateRule.getBrandId() == -1L) {
                    brandIds = new ArrayList<>();
                    vendorIdForBrandIdMap.put(vendorId, brandIds);
                } else {
                    brandIds = vendorIdForBrandIdMap.get(vendorId);
                    if (brandIds.contains(-1L)) {
                        continue;
                    }
                }
            } else {
                brandIds = new ArrayList<>();
                vendorIdForBrandIdMap.put(vendorId, brandIds);
            }
            brandIds.add(aggregateRule.getBrandId());
        }

        Long startTime = System.currentTimeMillis();
        //循环处理多个vendor，将vendor的在聚合规则中的商品查出来
        for (Map.Entry<Long, List<Long>> entry : vendorIdForBrandIdMap.entrySet()) {

            Long vendorId = entry.getKey();
            List<Long> brandIds = null;
            if (!entry.getValue().contains(-1L)) {
                brandIds = entry.getValue();
            }
            int pos = 0;
            Long productId = 0L;
            while (true) {
                List<Product> listProduct = aggregateService.getUnAggregatedProductInRule(productId, pos, PROCESS_PRODUCT_NUM, vendorId, brandIds);
                for (Product product : listProduct) {
                    LOGGER.debug("product {}-{} designer {} color {} .", product.getProductId(), product.getName(), product.getDesignerId(),
                            product.getColorCode());
                    try {
                        aggregateService.aggregateProduct(product);
                        productId = product.getProductId();
                    } catch (Exception e) {
                        productId = product.getProductId();
                        LOGGER.debug("Could not aggregate product {}.", product.getProductId());
                    }
                }
                if (listProduct.size() < PROCESS_PRODUCT_NUM) {
                    break;
                }
            }
        }
//        Long productId = 0L;
//        while (true) {
//            List<Product> listProduct = aggregateService.getUnAggregatedProduct(productId, pos, PROCESS_PRODUCT_NUM);
//            for (Product product : listProduct) {
//                LOGGER.debug("product {}-{} designer {} color {} .", product.getProductId(), product.getName(), product.getDesignerId(),
//                        product.getColorCode());
//                try {
//                    aggregateService.aggregateProduct(product);
//                    productId = product.getProductId();
//                } catch (Exception e) {
//                    productId = product.getProductId();
//                    LOGGER.debug("Could not aggregate product {}.", product.getProductId());
//                }
//            }
//            //            pos += listProduct.size();
//
//            if (listProduct.size() < PROCESS_PRODUCT_NUM) {
//                break;
//            }
//        }

        LOGGER.info("It takes {}ms for aggregate product.", System.currentTimeMillis() - startTime);
        LOGGER.info("*********************************************************");
        LOGGER.info("*****************Aggregate product finish****************");
        LOGGER.info("*********************************************************");
    }
}
